#include "TMux.h"

int Mux_Crear(TMux* mux) {
	int salida;

	mux->placa = NULL;
	mux->mensajes = (TListaMensajes*) malloc(sizeof(TListaMensajes));
	if (!(mux->mensajes)) {
		return MUX_ERR_MEMORIA;
	}

	salida = LM_Crear(mux->mensajes);
	switch (salida) {
		case TLM_OK:
			return MUX_OK;
		case TLM_ERR_MEMORIA:
			return MUX_ERR_MEMORIA;
		default:
			return MUX_ERR_DESCONOCIDO;
	}

  mux->placa = NULL;
  mux->mensajes = (TListaMensajes*) malloc(sizeof(TListaMensajes));
  LM_Crear(mux->mensajes);
	return MUX_OK;
}

int Mux_Destruir(TMux* mux) {
	Mux_Desconectar(mux);
	LM_Destruir(mux->mensajes);
	free(mux->mensajes);
	return MUX_OK;
}

int Mux_Conectar(TMux* mux, TPlaca* placa) {
	int error;

	if (mux->placa == NULL) {
		mux->placa = placa;
		return MUX_OK;
	}
	else {
		return MUX_ERR_PLACACONECTADA;
	}
}

int Mux_Desconectar(TMux* mux) {
	mux->placa = NULL;
	return MUX_OK;
}

int Mux_Recibir(TMux* mux, void* mensaje, size_t tam) {
	int codigo_error;

	#ifdef __DEBUG__
    printf("Mux_Recibir:\n Entra.\n");
    #endif

	codigo_error = LM_InsertarMensaje(mux->mensajes, mensaje);

	if (codigo_error) {
	    return MUX_ERR_MENSAJEINSERTAR;
	}
	else {
		return MUX_OK;
	}
}

int Mux_Enviar(TMux* mux, void* mensaje, size_t tam, TDireccion dir, TPuerto puerto, int prioritario) {
	int codigo_error;
	TMensaje* m;
	m = malloc(sizeof(TMensaje));

	codigo_error = Mensaje_Crear(m, dir, (char*)mensaje, prioritario, puerto);

	if (codigo_error) {
		free(m);
		switch (codigo_error) {
			case MENSAJE_ERR_MEMORIA:
				return MUX_ERR_MEMORIA;
				break;
			case MENSAJE_ERR_STRVACIO:
				return MUX_ERR_MENSAJESTRVACIO;
				break;
			default:
				return MUX_ERR_INESPERADO;
		}
	}

	codigo_error = Placa_Enviar(mux->placa, m, tam, dir);

	#ifdef __DEBUG__
	printf("Mux_Enviar: Mensaje Enviado.\n");
	#endif

	if (codigo_error) {
		free(m);
		/* TODO: interpretar error y return */
		switch (codigo_error) {
		    case 99:{
				return MUX_ERR_MEDIOTRANSMITIR;
				break;
		    }
			default:
				return MUX_ERR_INESPERADO;
		}
	}
	else {
		/*free(m);*/
		return MUX_OK;
	}
}

/* Criterio: primero saco un mensaje prioritario; si no hay, saco uno no-prioritario */
size_t Mux_Leer(TMux* mux, TPuerto puerto, void* destino) {
	int codigo_error = MUX_OK;
	TMensaje* mensaje;

    #ifdef __DEBUG__
    printf("Mux_Leer:\n Direccion mux = %x\n", mux);
    #endif

	mensaje = malloc(sizeof(TMensaje));
	codigo_error = LM_ObtenerMensaje(mux->mensajes, puerto, PRIORITARIO, mensaje);

    #ifdef __DEBUG__
    printf("Mux_Leer:\n Problema LM_ObtenerMensaje = %d\n", codigo_error);
    #endif

	if (codigo_error == /*TLM_OK*/ 0) {
		codigo_error = Mensaje_ObtenerTexto(mensaje, (char**)&destino);
	}
	else if (codigo_error == /*TLM_ERR_SINMENSAJES*/ 2) {
		codigo_error = MUX_ERR_NOHAYMENSAJESENPUERTO;
	}
	else {
		codigo_error = LM_ObtenerMensaje(mux->mensajes, puerto, NO_PRIORITARIO, mensaje);
		if (codigo_error == /*TLM_OK*/ 0) {
			codigo_error = Mensaje_ObtenerTexto(mensaje, (char**)&destino);
		}
	}

	free(mensaje);
	return codigo_error;
}

